//
//  NSDate+PPKit.swift
//  PPKit
//
//  Created by cdmac on 16/9/19.
//  Copyright © 2016年 chinadailyhk. All rights reserved.
//  https://gitee.com/xiaopindev/PPKit
//  https://github.com/xiaopindev
//  https://xiaopin.cnblogs.com

import Foundation
import SwiftDate

/*
 
 https://github.com/malcommac/SwiftDate
 
 默认时间是UTC时间
 
 时间常用用法：
 
 初始化：
 Date()
 Date(seconds: 1601097039)    根据时间戳创建创建时间，单位秒
 Date(milliseconds: 1601097039000)  根据时间戳创建创建时间，单位毫秒
 
 1601097039.toDate()           时间戳转日期
 "2010-05-20 15:30:00".toDate() 字符串转日期
 
 获取属性：
 dateObj.monthName(.default)   //五月，April
 dateObj.monthName(.short)     //5月,Jun
 dateObj.monthDays             //获取当前日期月份有几天
 dateObj.day                   //获取这个月的第几天
 dateObj.dayOfYear             //一年当中的第几天
 hour，minute，second             //时分秒
 dateObj.weekday                    //从1：星期日 。。。7星期六
 dateObj.weekdayName(.default)      //星期四，Wednesday
 dateObj.weekdayName(.short)       //周四， Wed
 dateObj.firstDayOfWeek           //获取当前日期 当周的第一天，周日为首日
 dateObj.lastDayOfWeek           //获取当前日期 当周的最后一天，周六为尾日
 dateObj.quarter                   //当期日期在第几个季度 1,2,3,4
 dateObj.quarterName(.default)       //季度名称: 第二季度 4th quarter
 dateObj.quarterName(.short)       //季度名称: 2季度 Q2
 dateObj.isToday（isYesterday,isTomorrow) //是否是今天，昨天，明天
 dateObj.isInWeekend(isInPast,isInFuture) //是否在周末，是否是过去时间，是否是未来时间
 
两个日期时间差：
 let date5 = Date("2020-10-10 11:11:00")
 let date7 = Date("2020-10-11 11:11:20")
 
 //单个属性时间差
 // in 参数可以选择：年月日时分秒等等
 date5!.difference(in: .second, from: date7!)
 
 //多个属性时间差,根据所配置的属性，得到差值
 [.year,.month,.day,.hour,.minute,.second] 可以配置年月周天时分秒
 let dict = date5!.differences(in: [.day,.hour,.minute,.second], from: date7!)
 
 // 时间运算：加减
 let _ = ("2010-05-20 15:30:00".toDate() + 3.months - 2.days)
 let _ = Date() + 3.hours
 let _ = date1 + [.year:1, .month:2, .hour:5]
 let _ = date1 + date2
 let over1Year = (date3 - date2).year > 1
 
 判断比较日期：
 判断日期早于或者晚于某个时间
 date1.earlierDate(date2)
 date1.laterDate(date2)
 
 更高级用法，可以指定粒度granularity
 基于：日历，date1是否在date2之后
 date1!.isAfterDate(date2!, granularity: .calendar)
 date1!.isBeforeDate(date2!, granularity: .calendar)
 基于：年，date1是否在date2之后或者一样的
 date1!.isAfterDate(date2!, orEqual: true, granularity: .year)
 date1!.isBeforeDate(date2!, orEqual: true, granularity: .year)
 
 判断日期时间是否是在早上，中午，晚上，夜晚，是否是当周，上周，下周，是否是同一天，同一周，同一年,是否是周末，是否是过去，是否是将来...等等
 date1.compare(.isAfternoon)
 
 
 日期格式
 公元
 G：顯示AD，也就是公元
 
 年
 yy：年，后面的两位数字
 yyyy：完整的年份
 
 月
 M：112，19显示一位数，10~12显示两位数字
 MM：01~12，显示两位数字
 MMM：英文的月份缩写
 MMMM：英文的月份全拼
 
 日
 d：131，19显示一位数，10~31显示两位数字
 dd：01~31，显示两位数字

 星期
 EEE：星期的缩写，Tue(英文)，周二（中文）
 EEEE：星期的全拼，Tuesday(英文)，星期二（中文）

 上午/下午
 aa：显示AM/PM

 小时
 H：023，09显示一位数，10~12显示两位数
 HH：0~23，显示两位数字
 K：012，09显示一位数，10~12显示两位数
 KK：0~12，显示两位数字

 分
 m：059，09显示一位数字，10~59显示两位数
 mm：0~59，显示两位数字

 秒
 s：059，00显示一位数字，10~59显示两位数
 ss：0~59，显示两位数字
 S：显示毫秒

 zzz: 时区
 ZZZ:
 **/

public enum DateFormatStyle:String {
    /// 格式：yyyy-MM-dd HH:mm:ss
    case `default` = "yyyy-MM-dd HH:mm:ss"
    /// 格式：yyyy-MM-dd
    case style1 = "yyyy-MM-dd"
    /// 格式：yyyy-MM-dd HH:mm
    case style2 = "yyyy-MM-dd HH:mm"
    /// 格式：yyyy-MM-dd HH:mm:ss zzz
    case style3 = "yyyy-MM-dd HH:mm:ss zzz"
    /// 格式：HH:mm
    case style4 = "HH:mm"
    /// 格式：mm:ss
    case style5 = "mm:ss"
    /// 格式：yyyy/MM/dd HH:mm
    case style6 = "yyyy/MM/dd HH:mm"
    /// 格式：yy/MM/dd
    case style7 = "yy/MM/dd"
    /// 格式：MM/dd HH:mm
    case style8 = "MM/dd HH:mm"
    /// 格式：yyyy/MM
    case style9 = "yyyy/MM"
    /// MM-dd HH:mm
    case style24 = "MM-dd HH:mm"
    
    /// 格式：yyyy年MM月dd日
    case style_CN01 = "yyyy年MM月dd日"
    /// 格式：yyyy年MM月
    case style_CN02 = "yyyy年MM月"
    /// 格式：MM月dd日
    case style_CN03 = "MM月dd日"
    /// 格式："MM月dd日 EEE"
    case style_CN04 = "MM月dd日 EEE"
    /// 英文格式: 03 Aug 2016
    case style_EN01 = "dd MMM yyyy"
    /// 英文格式: Aug 03, 2016 (美式)
    case style_EN01_1 = "MMM dd,yyyy"
    /// 英文格式: Aug 2016
    case style_EN02 = "MMM yyyy"
    /// 格式：01 Aug
    case style_EN03 = "dd MMM"
    /// 英文格式: EEE, dd MMM
    case style_EN04 = "EEE, dd MMM"
    
    /// MM-dd\nHH:mm
    case style_custom01 = "MM-dd\nHH:mm"
    /// MM.dd HH:mm
    case style_custom02 = "MM.dd HH:mm"
    /// yyyy.MM.dd
    case style_custom03 = "yyyy.MM.dd"
    
}

/// 当前0时区UTC日期时间
func ntpDate() -> Date{
    return NTPTime.shared.ntpDate()
}

/// 当前0时区UTC时间戳
func ntpTimestamp() -> TimeInterval{
    return TimeInterval(Int(NTPTime.shared.ntpTimestamp()))
}

public extension Date {
    
    /// 通过这个方式获取中国大陆的日期时间字符串
    /// - Parameter format: <#format description#>
    /// - Returns: <#description#>
    func toString(_ format:DateFormatStyle = .default) -> String {
        let dateFormatter = DateFormatter()
        dateFormatter.timeZone = .current
        dateFormatter.dateFormat = format.rawValue
        return dateFormatter.string(from: self)
    }
    
    func toString(_ format:DateFormatStyle = .default, langCode:String = "en-US") -> String {
        let dateFormatter = DateFormatter()
        dateFormatter.locale = Locale(identifier: langCode)
        dateFormatter.dateFormat = format.rawValue
        return dateFormatter.string(from: self)
    }
    
    /// 如果toString不满足需求，可以自定义format格式
    /// - Parameter format: <#format description#>
    /// - Returns: <#description#>
    func format(_ format: String, langCode:String = "en-US") -> String {
        let dateFormatter = DateFormatter()
        //dateFormatter.timeZone = .current
        dateFormatter.locale = Locale(identifier: langCode)
        dateFormatter.dateFormat = format
        return dateFormatter.string(from: self)
    }

    /// 获取周几，也可以直接用：.weekdayName(.short)， 显示星期几用：.weekdayName(.default)
    /// - Returns: <#description#>
    func weekdayName() -> String {
        let calendar = Calendar.init(identifier: .gregorian)
        let unitFlags:Set<Calendar.Component> = [.year , .month , .day , .hour , .minute, .weekday, .weekOfMonth]
        let comps = calendar.dateComponents(unitFlags, from: self)
        switch comps.weekday {
        case 1:
            return "MT_Week_Sun".localized
        case 2:
            return "MT_Week_Mon".localized
        case 3:
            return "MT_Week_Tus".localized
        case 4:
            return "MT_Week_Wen".localized
        case 5:
            return "MT_Week_Thu".localized
        case 6:
            return "MT_Week_Fri".localized
        case 7:
            return "MT_Week_Sat".localized
        default:
            break
        }
        return ""
    }
    
    func isToday() -> Bool{
        let start = Date().format("yyyy-MM-dd 00:00:00").toDate()
        let end = Date().format("yyyy-MM-dd 23:59:59").toDate()
        return start <= self && self <= end
    }

    func isYesterday() -> Bool {
        let start = (Date() - 1.days).format("yyyy-MM-dd 00:00:00").toDate()
        let end = (Date() - 1.days).format("yyyy-MM-dd 23:59:59").toDate()
        return start <= self && self <= end
    }
    
    func isTomorrow() -> Bool {
        let start = (Date() + 1.days).format("yyyy-MM-dd 00:00:00").toDate()
        let end = (Date() + 1.days).format("yyyy-MM-dd 23:59:59").toDate()
        return start <= self && self <= end
    }
}

public extension Double{
    /// 时间戳转UTC日期
    /// - Returns: <#description#>
    func toDate() -> Date{
        return Date(timeIntervalSince1970: self)
    }
    
    /// 时间戳转UTC日期格式化成字符串
    /// - Parameter format: <#format description#>
    /// - Returns: <#description#>
    func toDateString(_ format:DateFormatStyle = .default) -> String {
        return self.toDate().toString(format)
    }

    /// 获取TimeAgoStr
    /// - Returns: <#description#>
    func toTimeAgo() -> String {
        return self.toDate().timeAgoSinceNow()
    }

    /// 仿微信聊天模式的时间格式
    /// - Returns: <#description#>
    func toTimeAgoForChat() -> String {
        return self.toDate().timeAgoSinceNow2()
    }
}

public extension String{
    /// 字符串转UTC日期
    /// - Parameter format: 默认：yyyy-MM-dd HH:mm:ss
    /// - Returns: <#description#>
    func toDate(_ format:DateFormatStyle = .default) -> Date {
        let dateFormatter = DateFormatter()
        dateFormatter.timeZone = .current //TimeZone(abbreviation: "UTC")
        dateFormatter.dateFormat = format.rawValue
        return dateFormatter.date(from: self) ?? Date()
    }
    
    /// 秒转hh:mm:ss
    func seconds2hhmmss() -> String {
        let allTime: Int = Int(Double(self)!)
        var hours = 0
        var minutes = 0
        var seconds = 0
        var hoursText = ""
        var minutesText = ""
        var secondsText = ""
        
        hours = allTime / 3600
        hoursText = hours > 9 ? "\(hours)" : "0\(hours)"
        
        minutes = allTime % 3600 / 60
        minutesText = minutes > 9 ? "\(minutes)" : "0\(minutes)"
        
        seconds = allTime % 3600 % 60
        secondsText = seconds > 9 ? "\(seconds)" : "0\(seconds)"
        
        return "\(hoursText):\(minutesText):\(secondsText)"
    }
}
